package org.xxpay.pay.channel.funpay;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.PayDigestUtil;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayNotify;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 支付回调
 */
@Service
public class FunpayPayNotifyService extends BasePayNotify {

    private static final MyLog _log = MyLog.getLog(FunpayPayNotifyService.class);
    private static final String logPrefix = "【处理"+ FunpayConfig.CHANNEL_NAME+"支付回调】";


    @Override
    public String getChannelName() {
        return FunpayConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject doNotify(Object notifyData) {
        _log.info("====== 开始处理{}支付回调通知 ======", FunpayConfig.CHANNEL_NAME);
        HttpServletRequest request = (HttpServletRequest) notifyData;
        JSONObject retObj = buildRetObj();
        Map<String, String> payContext = new HashMap();

        String respString = FunpayConfig.RETURN_VALUE_ERROR;
        try {
            PayOrder payOrder = verifyPayParams(request, payContext);
            if( payOrder == null ) { //验证参数失败
                retObj.put(PayConstant.RESPONSE_RESULT, FunpayConfig.RETURN_VALUE_ERROR);
                return retObj;
            }
            //订单已经支付完成
            if(payOrder.getStatus() == PayConstant.PAY_STATUS_SUCCESS || payOrder.getStatus() == PayConstant.PAY_STATUS_COMPLETE){
                retObj.put(PayConstant.RESPONSE_RESULT, FunpayConfig.RETURN_VALUE_SUCCESS);
                return retObj;
            }
            //上游通知 状态
            String channelOrderNo = payContext.get("queryId"); //上游订单号

            int updatePayOrderRows = commonService.payOrderService.updateStatus4Success(payOrder.getPayOrderId(), channelOrderNo);
            if (updatePayOrderRows != 1) {
                _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
                retObj.put(PayConstant.RESPONSE_RESULT, "处理订单失败");
                return retObj;
            }
            _log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
            payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);

            // 业务系统后端通知
            baseNotify4MchPay.doNotify(payOrder, true);
            _log.info("====== 完成处理{}支付回调通知 ======", FunpayConfig.CHANNEL_NAME);
            respString = FunpayConfig.RETURN_VALUE_SUCCESS;
        } catch (Exception e) {
            _log.error(e, logPrefix + "处理异常");
        }
        retObj.put(PayConstant.RESPONSE_RESULT, respString);
        return retObj;
    }

    /**
     * 验证通知参数
     * @return
     */
    private PayOrder verifyPayParams(HttpServletRequest req, Map<String, String> payContext) {

        try {
            // 验证参数是否合法
            String code = req.getParameter("code");         // 返回状态码
            String msg = req.getParameter("msg");         // 返回信息
            String mchId = req.getParameter("mchId");         // 商户编号
            String orderId = req.getParameter("orderId");           // 订单号
            String tradeNo = req.getParameter("tradeNo");         // 交易流水号
            String amount = req.getParameter("amount");         // 订单金额
            String status = req.getParameter("status");         // 交易状态
            String appType = req.getParameter("appType");         // 交易类型
            String sign = req.getParameter("sign");         // 签名
            String detail = req.getParameter("detail");         // 签名

            _log.info("{}code={}, msg={}, amount={}, mchId={}, orderId={}, tradeNo={}, status={}, appType={}, sign={}" ,
                    logPrefix, code, msg, amount, mchId, orderId, tradeNo ,status, appType, sign);

            if (!"SUCCESS".equals(code)) {
                _log.error("{}返回状态错误；code={}, msg={}", logPrefix, code, msg);
                return null;
            }

            if(!"SUCCESS".equals(status)) {
                _log.info("[{}]:orderid={} 返回失败", getChannelName(), status);
                return null;
            }

            PayOrder payOrder = commonService.payOrderService.findByPayOrderId(orderId); // 根据orderid查单
            if(payOrder == null){
                _log.error("{}订单不存在orderNo={}", logPrefix, orderId);
                return null;
            }

            FunpayConfig funpayConfig = new FunpayConfig(getPayParam(payOrder));

            Map<String, String> params = new HashMap<>();
            params.put("code", code);
            params.put("msg", msg);
            params.put("amount", amount);
            params.put("mchId", mchId);
            params.put("orderId", orderId);
            params.put("tradeNo", tradeNo);
            params.put("status", status);
            params.put("appType", appType);
            params.put("detail", detail);

            String myselfSign = PayDigestUtil.getSign(params, funpayConfig.getKey()).toLowerCase();

            if(!myselfSign.equals(sign)){
                _log.error("{}验签失败", logPrefix);
                return null;
            }

            payContext.put("queryId", tradeNo);
            return payOrder;
        } catch (Exception e) {
            _log.error("验证响应数据异常", e);
        }

        return null;

    }
}
